<template>
  <div>
    <el-upload
      :action="dataObj.host"
      :data="dataObj"
      list-type="picture"
      :multiple="multiple"
      :show-file-list="$slots.list == null"
      :file-list="fileList"
      :on-remove="handleRemove"
      :on-success="handleUploadSuccess"
      v-show="!props.custom"
    >
      <template #trigger>
        <el-button type="primary" link @click="refreshPolicy" ref="uploadButtonInstance">{{
          fileList.length > 0 ? '重新上传' : '点击上传'
        }}</el-button>
      </template>
      <template #tip>
        <div class="el-upload__tip" v-if="tip !== null">{{ tip }}</div>
      </template>
      <!--将数据给父组件，让父组件自定义显示-->
    </el-upload>
    <slot name="custom" :listData="fileUrlList" :select="manualUploadFile"></slot>
  </div>
</template>

<script lang="ts" setup>
import { ref, watch } from 'vue'
import { policy } from './policy'
import { getUUID } from '@/utils/uuidGen.ts'
import { UploadFile, UploadFiles, UploadUserFile } from 'element-plus'
// 上传组件实例-手动触发上传
const uploadButtonInstance = ref()
const manualUploadFile = () => {
  uploadButtonInstance.value.$el.click()
}
const emit = defineEmits(['update:modelValue'])
const props = defineProps({
  // 父组件 v-model 没有指定参数名，则默认是 modelValue
  modelValue: {},
  showFileListRef: {
    type: Boolean,
    default: true
  },
  tip: {
    type: String,
    default: null
  },
  multiple: {
    type: Boolean,
    default: false
  },
  custom: {
    type: Boolean,
    default: false
  }
})

const fileList = ref<UploadUserFile[]>([])
const fileUrlList = ref<string[]>()
watch(
  () => props.modelValue,
  (val) => {
    if (val == null) {
      fileUrlList.value = []
    } else {
      fileUrlList.value = val instanceof Array ? val : [val]
    }
  },
  { immediate: true }
)
function emitInput(resultFiles: UploadUserFile[]) {
  fileUrlList.value = resultFiles.map((resultFile) => resultFile.url)
  // 如果是单文件上传，不应该返回数组
  emit('update:modelValue', props.multiple ? fileUrlList : fileUrlList.value[0])
  console.log(props.multiple ? fileUrlList : fileUrlList.value[0])
}
function addFileList(uploadFile: UploadUserFile, uploadFiles: UploadFiles) {
  if (props.multiple) {
    fileList.value.push(uploadFile)
  } else {
    fileList.value[0] = uploadFile
  }
  emitInput(fileList.value)
  // 如果不是多选的且超过了，弹出前面的
  while (!props.multiple && uploadFiles.length > 1) uploadFiles.shift()
}

const dataObj = ref({
  policy: '',
  signature: '',
  key: '',
  ossaccessKeyId: '',
  dir: '',
  host: ''
})

function handleRemove(uploadFile: UploadFile, uploadFiles: UploadFiles): void {
  // 过滤掉fileList的uploadFile
  for (let i = 0; i < fileList.value.length; i++) {
    if (fileList.value[i].name === uploadFile.name) fileList.value.splice(i, 1)
  }
  // 过滤掉uploadFiles中的uploadFile
  for (let i = 0; i < uploadFiles.length; i++) {
    if (uploadFiles[i].name === uploadFile.name) uploadFiles.splice(i, 1)
  }
  // 修改v-model值
  emitInput(fileList.value)
}

async function refreshPolicy() {
  try {
    const { data } = await policy()
    dataObj.value.signature = data.signature
    dataObj.value.ossaccessKeyId = data.accessid
    dataObj.value.key = data.dir + getUUID() + '_${filename}'
    dataObj.value.dir = data.dir
    dataObj.value.host = data.host
    dataObj.value.policy = data.policy
    return true
  } catch (err) {
    return false
  }
}
function handleUploadSuccess(response: any, uploadFile: UploadFile, uploadFiles: UploadFiles): void {
  const fileUrl = dataObj.value.host + '/' + dataObj.value.key.replace('${filename}', uploadFile.name)
  addFileList({ name: uploadFile.name, url: fileUrl }, uploadFiles)
}
</script>

<style scoped lang="scss"></style>
